﻿// ***********************************************************************
// Assembly         : Invisionware.API.Amazon
// Author           : Shawn Anderson (sanderson@eye-catcher.com)
// Created          : 01-10-2014
//
// Last Modified By : Shawn Anderson
// Last Modified On : 01-19-2014
// ***********************************************************************
// <copyright file="ItemDataTypes.cs" company="Invisionware">
//     Copyright (c) Invisionware. All rights reserved.
// </copyright>
// <summary></summary>
// ***********************************************************************

using System;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
using System.Xml.Linq;

namespace Invisionware.API.Amazon
{
	/// <summary>
	/// Class ItemAPI.
	/// </summary>
	public class AwsItemOperations
	{
		#region Member Varaibles
		/// <summary>
		/// The _helper
		/// </summary>
		private AwsSignedRequestHelper _helper;
		#endregion Member Varaibles

		#region Constructors
		/// <summary>
		/// Initializes a new instance of the <see cref="AwsItemOperations" /> class.
		/// </summary>
		public AwsItemOperations()
		{
			Options = new AwsCommonOptions();
		}
		#endregion Constructors

		#region Public Properties
		public AwsCommonOptions Options { get; set; }
		#endregion Public Properties

		#region Public Methods
		/// <summary>
		/// Lookups the specified item code.
		/// </summary>
		/// <param name="lookupOptions">The lookup options.</param>
		/// <returns>XElement.</returns>
		public XElement Lookup(AwsItemLookupOptions lookupOptions)
		{
			Initialize();

			var commonOptionsDictionary = Options.Prepare(AwsItemOperationTypes.ItemLookup);
			var lookupOptionsDictionary = lookupOptions.Prepare();

			var r1 = commonOptionsDictionary.Merge(lookupOptionsDictionary);

			var requestUrl = _helper.Sign(r1);

			// Name				Description
			// ---------------	-------------------------------------------------------------------------------------------------
			// ASIN 			Amazon Standard Identification Number, which is an alphanumeric token assigned by Amazon to an 
			//					item that uniquely identifies it.
			// Item 			Container for information about the item, including ASIN, Title, ProductGroup. and Manufacturer.
			// ItemAttributes 	Container for information about an item, including Title, ProductGroup. and Manufacturer.
			// Items 			Container for one or more Item(s).
			// Manufacturer 	Name of the company that manufactured the item.
			// ProductGroup 	Category of the item, for example, “Book,” “DVD.” You can find the complete list of product 
			//					groups by going to www.amazon.com and clicking the tab that says "See All 32 Product Categories."
			// Title 			Title of the item. 

			var result = FetchData(this, requestUrl);

			return result.Result;
		}

		/// <summary>
		/// Searches the specified options.
		/// </summary>
		/// <param name="searchOptions">The options.</param>
		/// <returns>XElement.</returns>
		public XElement Search(AwsItemSearchOptions searchOptions)
		{
			Initialize();

			var commonOptionsDictionary = Options.Prepare(AwsItemOperationTypes.ItemSearch);
			var searchOptionsDictionary = searchOptions.Prepare();

			var r1 = commonOptionsDictionary.Merge(searchOptionsDictionary);

			var requestUrl = _helper.Sign(r1);

			// Name						Description
			// ----------------------	------------------------------------------------------------------------------------------
			// ASIN 					Amazon Standard Identification Number, which is an alphanumeric token assigned by Amazon to 
			//							an item that uniquely identifies it.
			// Item 					Container for item information, including ASIN and ItemAttributes.
			// ItemAttributes 			Container for information about an item, including Manufacturer, ProductGroup, and Title.
			// Manufacturer 			Item’s manufacturer.
			// MoreSearchResultsURL 	The URL where the complete search results are displayed. The URLs provided in the search 
			//							results are the exact ones that you should use when you link back to Amazon.com. They are 
			//							tagged with your Associate tag and contain other tracking information to increase your hourly 
			//							request limit as the sales that you generate increase.
			// ProductGroup 			Product category; similar to search index.
			// Title 					Item’s title.
			// TotalPages 				Total number of pages in response. There are up to ten items per page.
			// TotalResults 			Total number of items found. 

			var result = FetchData(this, requestUrl);

			return result.Result;
		}
		#endregion Public Methods

		#region Private Methods
		/// <summary>
		/// Fetches the data.
		/// </summary>
		/// <param name="sender">The sender.</param>
		/// <param name="url">The URL.</param>
		/// <returns>Task{XElement}.</returns>
		private static async Task<XElement> FetchData(AwsItemOperations sender, string url)
		{
			var validRequest = false;

			try
			{
				var client = new HttpClient();
				var response = await client.GetAsync(url);

				response.EnsureSuccessStatusCode();
				var content = await response.Content.ReadAsAsync<XElement>();
				XNamespace ns = sender.Options.AwsNameSpace;
				var isValidResults = content.Descendants(ns + "IsValid").AsParallel();

				foreach (var item in isValidResults)
				{
					if (item.Value == "True")
						validRequest = true;
					else
						return new XElement("Error", "Invalid Request");
				}

				if (validRequest)
				{
					return content;
				}

			}
			catch (Exception e)
			{
				System.Diagnostics.Trace.WriteLine("Caught Exception: " + e.Message);
				System.Diagnostics.Trace.WriteLine("Stack Trace: " + e.StackTrace);
			}

			return null;
		}

		/// <summary>
		/// Initializes this instance.
		/// </summary>
		private void Initialize()
		{
			_helper = new AwsSignedRequestHelper(Options.AccessKeyId, Options.AccessKeySecret, Options.AwsServiceUrl);
		}
		#endregion Private Methods
	}
}